package com.example.testplanetorbit

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View

/**
 * 星期轨道运行控件
 */
class OrbitsView : View {
    constructor(context: Context) :super(context) {
        initData()
    }

    constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet) {
        initData()
    }



    companion object {
        const val TOUCH_DEGRESS_MIN = -45.0f  //最大倾斜角度
        const val TOUCH_DEGRESS_MAX = -30.1f  //最小倾斜角度

        const val TOUCH_SENSITIVITY = 5f  //判断移动或者操作上的灵敏度
    }

    var paint: Paint? = null
    var touchRadio = 1.0f
    var touchRadioR = 0.1f

    private fun changeVerticalR(up:Boolean) {
        if (up) {
            if (touchRadio < 1.0f) {
                touchRadio += touchRadioR
            } else {
                touchRadio = 1.0f
                return
            }
        } else {
            if (touchRadio > 0.0f) {
                touchRadio -= touchRadioR
            } else {
                touchRadio = 0.0f
                return
            }
        }
        Log.d(TAG, "changeVerticalR::up = $up, touchRadio = $touchRadio")

        orbitDatas.forEach {
            it.changeVerticalR(touchRadio)
        }
        resetPath = true
        invalidate()
    }


    val TAG = "OrbitsView"

    var centerX = 0.0f
    var centerY = 0.0f

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        val save = canvas?.save()?:return

        canvas?.drawColor(Color.DKGRAY)
        initPaints()
        if (width != 0 && height != 0) {
            centerX = width / 2.0f
            centerY = height / 2.0f
            orbitDatas.forEach {
                it.setParentSize(width, height)
            }
        }

        canvas?.rotate(orbitData1.getDegress()?:-45f, width * 1.0f / 2, height * 1.0f / 2)

        orbitDatas.forEach {
            it.drawRectF(canvas)
        }

        orbitDatas.forEach {
            it.setPathMeasure1()
        }
        drawOval(canvas)

        canvas?.restoreToCount(save)

        orbitDatas.forEach {
            it.drawText(canvas)
        }
        orbitDatas.forEach {
            it.resetPath()

        }
    }

    private fun initPaints() {
        if (paint == null) {
            paint = Paint()
            paint?.isAntiAlias = true
            paint?.color = Color.WHITE
            paint?.style = Paint.Style.STROKE
            paint?.strokeWidth = 0.8f
        }
    }

    var resetPath = false


    val orbitData1: OrbitData = InnerOrbit()
    val orbitData2 : OrbitData = SecondOrbit()
    val orbitData3 : OrbitData = SecondOrbit()
    val orbitData4 : OrbitData = SecondOrbit()
    val orbitData5 : OrbitData = SecondOrbit()
    var orbitDatas = arrayListOf<OrbitData>()

    fun initData() {
        orbitData1.init(OrbitData.OvalConfig(
            190,170, 190,
            90, 120, 90, -45f,
            orbitColor = "#DDDDDD",
            arrayListOf(),
            1
        ))

        val data1 = OvalTagDot.Data("sdfgsd2", "刘德华", "2342", "")
        val data2 =OvalTagDot.Data("sdfgsd3", "中岛美雪", "232", "")

        val data3 = OvalTagDot.Data("sdfgsd4", "许巍", "2342", "")
        val data4 =OvalTagDot.Data("sdfgsd5", "朴树", "22", "")

        val data5 = OvalTagDot.Data("sdfgsd6", "刘德华", "2", "")
        val data6 =OvalTagDot.Data("sdfgsd7", "Avicil", "22", "")

        val data7 = OvalTagDot.Data("sdfgsd6", "Arbor Kevin", "122", "")
        val data8 =OvalTagDot.Data("sdfgsd7", "卡龙", "545632", "")

        orbitData2.init(OrbitData.OvalConfig(
            orbitColor = "#CCCCCC",
            tags = arrayListOf(data1, data2), circle = 2
        ))
        orbitData3.init(OrbitData.OvalConfig(
            orbitColor = "#999999",
            tags = arrayListOf(data3, data4), circle = 3
        ))
        orbitData4.init(OrbitData.OvalConfig(
            orbitColor = "#888888",
            tags = arrayListOf(data5, data6), circle = 4
        ))
        orbitData5.init(OrbitData.OvalConfig(
            orbitColor = "#777777",
            tags = arrayListOf(data7, data8), circle = 5
        ))
        orbitDatas.add(orbitData1)
        orbitDatas.add(orbitData2)
        orbitDatas.add(orbitData3)
        orbitDatas.add(orbitData4)
        orbitDatas.add(orbitData5)
    }

    private fun drawOval(canvas: Canvas?) {
        orbitDatas.forEach {
            it.drawOval1(canvas)
        }
        invalidate()
    }

    val lastPoint = PointF()
    val downPoint = PointF()
    var noMove = false
    var noRotate = false
    var lastClickTime = 0L

    override fun onTouchEvent(event: MotionEvent): Boolean {
        Log.d(TAG, "onTouchEvent :: event = $event")
        if (event?.action == MotionEvent.ACTION_DOWN) {
            lastClickTime = System.currentTimeMillis()
            lastPoint.x = event.x
            lastPoint.y = event.y
            downPoint.x = event.x
            downPoint.y = event.y
            lockMove(true)
            return true
        }
        if (event.action == MotionEvent.ACTION_MOVE) {
            noMove = false
            noRotate = false
            if (event.y > lastPoint.y + TOUCH_SENSITIVITY) {
                changeVerticalR(true)
            } else if (event.y < lastPoint.y - TOUCH_SENSITIVITY) {
                changeVerticalR(false)
            } else {
                noMove = true
            }

            if (event.x > lastPoint.x + TOUCH_SENSITIVITY) {
                changeDegress(true)
            } else if (event.x < lastPoint.x - TOUCH_SENSITIVITY) {
                changeDegress(false)
            } else {
                noRotate = true
            }

            if (noRotate && noMove) {
                lockMove(true)
            } else {
                if (centerX > 0f && centerY > 0f) {
                    if (!isCCW(event)) {
                        lockMove(false)
                        orbitDatas.forEach {
                            it.changeHorizontal(true)
                        }
                    } else {
                        lockMove(false)
                        orbitDatas.forEach {
                            it.changeHorizontal(false)
                        }
                    }
                }
            }
            lastPoint.x = event.x
            lastPoint.y = event.y
        }
        if (event.action == MotionEvent.ACTION_UP) {
            lockMove(false)
            if (System.currentTimeMillis() - lastClickTime <= 200) {
                //认为是点击事件
                orbitDatas.forEach {
                    val data = it.clickDot(PointF(event.x, event.y))
                    Log.d(TAG, "data = ${data?.tagName}, ${data?.count}")
                    if (data != null) {
                        taglistener?.onClick(data)
                        return super.onTouchEvent(event)
                    }
                }
            }
        }
        return super.onTouchEvent(event)
    }

    /**
     * Tag点击事件
     */
    var taglistener : OnClickTagListener? = null
    interface OnClickTagListener {
        fun onClick(data : OvalTagDot.Data?)
    }

    /**
     * 是否逆时针旋转
     */
    private fun isCCW(event: MotionEvent) :Boolean {
        Log.d(TAG, "isOvalOrbit::lastIsOvalOrbit = $lastIsOvalOrbit")
        var retVal = if (event.x >= centerX && event.y >= centerY) {
            event.x > lastPoint.x
        } else if (event.x <= centerX && event.y <= centerY) {
            event.x < lastPoint.x
        } else if (event.x > centerX && event.y < centerY) { //右上角
            (centerY - event.y) / (event.x - centerX) > (centerY - lastPoint.y) / (lastPoint.x - centerX)
        } else if (centerX > event.x && event.y > centerY) { //左下角
            (event.y - centerY) / (centerX - event.x) > (lastPoint.y - centerY) / (centerX - lastPoint.x)
        } else {
            lastIsOvalOrbit
        }
        lastIsOvalOrbit = retVal
        Log.d(TAG, "isOvalOrbit::retVal = $retVal")
        return retVal
    }
    private var lastIsOvalOrbit = false

    private fun changeDegress(up: Boolean) {
        Log.d(TAG, "changeDegress::up = $up")
        orbitDatas.forEach {
            it.changeDegress(up)
        }
    }

    /**
     * 手指按下时，没有拖动，则锁定，不运行轨道
     */
    private fun lockMove(lock: Boolean) {
        orbitDatas.forEach {
            it.setStepLock(lock)
        }
    }

}